/******************************************************************************
 *  _____     _____
 *  \  __\    \  __\
 *   \ \_\\    \ \_\\
 *    \  __\SS  \  __\roject
 *     \_\       \_\
 *
 * Mateusz Maciąg, Rafał Urbański
 * Komputerowe Systemy Sterowania
 *****************************************************************************/

#include "KroneckerWaveform.h"

#include <cmath>
#include <sstream>

#include "Utils.h"

namespace RafMat
{
namespace SimEngine
{

using namespace std;
using namespace SimInterface;

const std::string KroneckerWaveform::CONF_PULSETIME = "action_time";
const std::string KroneckerWaveform::CONF_INIT = "init_val";
const std::string KroneckerWaveform::CONF_PULSEVALUE = "action_val";

KroneckerWaveform::KroneckerWaveform(SimInterface::ISimulator& sim,
                                     double initVal, double pulseTime,
                                     double pulseValue)
    : WaveformBase(sim, "Kronecker", "kronecker", pulseValue, pulseTime, initVal, 0)
{
}

double KroneckerWaveform::getNextValue()
{
    double currentTime = getCurrentTime();

    return getOffset() + (currentTime == getPeriod() ? getGain() : 0);
}

bool KroneckerWaveform::setParameter(const string& param, const string& value) throw(logic_error)
{
    // Usuń ewentualne wiodące i końcowe spacje
    string tparam = Utils::trimWhiteSpaces(param);
    string tvalue = Utils::trimWhiteSpaces(value);

    // Strumień danych dla łańcucha argumentu.
    istringstream istr(tvalue);

    double tmpVal;

    void (KroneckerWaveform::*setter)(double);

    if(tparam == CONF_PULSETIME)
        setter = &KroneckerWaveform::setPulseTime;
    else if(tparam == CONF_INIT)
        setter = &KroneckerWaveform::setInitVal;
    else if(tparam == CONF_PULSEVALUE)
        setter = &KroneckerWaveform::setPulseVal;
    else
        return WaveformBase::setParameter(param, value);

    istr >> tmpVal;
    if(!istr.bad())
    {
        (this->*setter)(tmpVal);
    }

    if(istr.bad())
    {
        throw iconf_error::syntaxError(*this, tvalue);
    }

    return true;
}

string KroneckerWaveform::getParameter(const string& param) const throw(logic_error)
{
    // Usuń ewentualne wiodące i końcowe spacje
    string tparam = Utils::trimWhiteSpaces(param);
    string outStr;

    // Strumień danych dla łańcucha argumentu.
    ostringstream ostr(outStr);

    if(tparam == CONF_PULSETIME)
        ostr << getPeriod();
    else if(tparam == CONF_INIT)
        ostr << getOffset();
    else if(tparam == CONF_PULSEVALUE)
        ostr << getGain();
    else
        return WaveformBase::getParameter(param);

    return ostr.str();
}

SimFile::ConfigWriter& KroneckerWaveform::dumpSpecificPar(SimFile::ConfigWriter& o) const
{
    o.pushParam(CONF_INIT, getInitVal());
    o.pushParam(CONF_PULSETIME, getPulseTime());
    o.pushParam(CONF_PULSEVALUE, getPulseVal());
    return o;
}

}   // SimEngine namespace
}   // RafMat namespace

